package com.xiangjun.proxytest.jdkdynamicproxytest.reflect;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class test {


    public static void main(String[] args) throws Exception {
        //反射获取类的几种方式
        //1、类未申明的时候可以这样获取
        //Class class1 = Person.class;

        //2、类声明后可以这样获取
        //Person pClass = new Person();
        //Class Class2 = pClass.getClass();
        //以上两种方式字节码都必须被加载到java虚拟机中去的时候才允许这样获取，若java虚拟机还没的这份字节码，则
        //需使用下面的方法
        //3、通过类名获取类
        //Class class3 = Class.forName("com.xiangjun.proxytest.dynamicproxytest.reflect.Person");

        //类包含成员变量、方法、构造方法、包、继承和实现关系

        //1、获取类的成员变量使用Field方法
        //获取这个类的name字节码对象，注意访问权限，private的需要开放权限才能访问
        Class<?> aClass = Class.forName("com.xiangjun.proxytest.jdkdynamicproxytest.reflect.Person");
        Field name = aClass.getDeclaredField("name");
        //私有的需要开放访问权限
        name.setAccessible(true);

        Field age = aClass.getDeclaredField("age");
        age.setAccessible(true);

        //获取所有的成员变量，遍历的时候可以使用
        Field[] declaredFields = aClass.getDeclaredFields();

        //如果成员变量是公有的，那么直接getField即可
        Person p = new Person();
        p.setName("张三");
        p.setAge(8);
        String sName = (String) name.get(p);
        Integer i = (Integer) age.get(p);
        System.out.println(sName);
        System.out.printf(i.toString());

        //获取指定类的方法，传入方法名，和方法入参的所有字节对象
        Method info = aClass.getMethod("info", String.class);
        String infoM = (String) info.invoke(p,"优秀");
        System.out.printf(infoM);

        //获取所有public方法
        Method[] methods = aClass.getMethods();

        //获取所有方法
        Method[] declaredMethods = aClass.getDeclaredMethods();


        //获取构造方法constructors 和上诉使用方法相差不大，

        //反射底层实现原理，涉及到JAVA虚拟机，待后续

        Class<?>[] interfaces = aClass.getInterfaces();
        for (Class<?> anInterface : interfaces) {

        }
    }
}
